package com.day16;

import org.junit.Test;

import java.util.*;

/**
 * 一.Map的实现类的结构:
 * | ----Map:双列数据，存储key-value对的数据 ---类似于高中的函数: y = f(x)
 * HashMap:作为Map的主要实现类,线程不安全的，效率高:存储null的key或value
 * LinkedHashMap:保证在遍历map元素时，可以按照添加的顺序实现遍历
 * 原因:在原有的HashMap的底层结构基础上，添加了一对指针。指向前一个和后一个元素
 * TreeMap:保证按照添加的key-value对进行排序，实现排序遍历，此时考虑key的自然排序和定制排序
 * 底层使用红黑树
 * Hashtable:作为古老的实现类,线程安全，效率低:不能存储null的key和value
 * Properties:常用量处理配置文件。key和value都是String类型
 * <p>
 * <p>
 * HashMap的底层: 数组 + 链表 (jdk7以及之前)
 * 数组 + 链表 + 红黑数(jdk8)
 * <p>
 * 面试题:
 * 1.HashMap的底层原理?
 * 2.HashMap 和 Hashtable的异同?
 * 3.CurrentHashMap 与 Hashtable的异同?
 * <p>
 * 二.Map结构的理解:
 * Map中的key:是无序的，不可重复的，使用Set去存储所有的Key,如果是HashMap就是HashSet  ---> key所在的类重写equals方法和hashCode()方法  、
 * (主要是以HashMap为例)
 * Map中的value是无序的，可重复的，使用Collection去存储所有的value  ---> value所在的类要重写equals()
 * 一个键值对: key-value构成了一个Entry对象
 * Map中的entry:无序的，不可重复的，使用Set存储所有的entry。
 * <p>
 * 三.HashMap的底层实现原理:
 * jdk7:
 * HashMap map = new HashMap();
 * 在实例化以后，底层创建了长度是16的一维数组Entry[] table。
 * ...可能已经执行过多次put了...
 * map.put(key1, value1);
 * 首先,调用key1所在类的hashCode()计算key1的哈希值，此哈希值经过某种算法计算以后，得到在Entry数组中的存放位置。
 * 如果此位置上的数据为空，此时的key1-value1添加成功。
 * <p>
 * 如果此位置上的数据不为空,意味着此位置上存在一个或多个数据(以链表的形式存在),比较当前的key1和已经存在的一个或多个数据的hash值
 * 1.如果key1的哈希值和已经存在的数据hash值都不相同，此时key1-value1添加成功。
 * 2.如果key1的哈希值和已经存在的某一个数据的hash值相同。继续比较:调用key1所在类的equals()方法,
 * 比较:如果equals()返回false;此时key1-value1添加成功
 */
public class MapTest {

    @Test
    public void test1() {
        Map map = new HashMap();

        map.put(null, null);

        Hashtable hashtable = new Hashtable();

        hashtable.put(null, null);
    }


    @Test
    public void test2() {

        HashMap hashMap = new HashMap();

        //添加
        hashMap.put("AA", 123);
        hashMap.put("BB", 123);
        hashMap.put("CC", 123);
        hashMap.put("DD", 123);
        //修改
        hashMap.put("DD", 1234);

        System.out.println(hashMap);

        HashMap hashMap1 = new HashMap();

        hashMap1.put("CC", 123);
        hashMap1.put("DD", 123);


        hashMap.putAll(hashMap1);

        System.out.println(hashMap);


        //remove(Object key):根据key移除键值对，并返回value
        Object cc = hashMap.remove("CC");

        System.out.println(cc);


        //clear():清空map方法
//        hashMap.clear();//与map = null 操作不同
//        System.out.println(hashMap.size());
//        System.out.println(hashMap);


        //get():根据key获取value值

        System.out.println(hashMap.get("AA"));

        //containsValue(Object obj):是否包含指定的value
        boolean b = hashMap.containsValue(123);

        //isEmpty():判断当前map是否为null
        System.out.println(hashMap.isEmpty());

    }

    /**
     * 遍历map
     */
    @Test
    public void test5() {
        Map hashMap = new HashMap();
        hashMap.put("AA", 123);
        hashMap.put("BB", 123);
        hashMap.put("CC", 123);
        hashMap.put("DD", 123);

        //遍历所有的key集:keySet()
        Set set = hashMap.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        //遍历所有的value集: values()
        Collection values = hashMap.values();
        for (Object value : values) {
            System.out.println(value);
        }


        //遍历所有的key-value:方式1
        Set set1 = hashMap.entrySet();
        Iterator iterator1 = set1.iterator();
        while (iterator1.hasNext()){
            Object next = iterator1.next();
            //entrySet集合中的元素都是Entry
            Map.Entry entry = (Map.Entry)next;
            Object key = entry.getKey();
            Object value = entry.getValue();


            System.out.println(entry);
        }


    }

    @Test
    public void test88(){
        Set set = new HashSet();
        set.add(1);
        set.add(1);
        set.add(1);
        set.add(1);
        set.add(1);
//        Iterator iterator = set.iterator();
//        while (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }
        for(Object i : set){
            System.out.println(i);
        }
    }

}



